package com.kcht.np.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kcht.np.common.exception.ParameterException;
import com.kcht.np.constant.DictStatus;
import com.kcht.np.entity.SysDictData;
import com.kcht.np.entity.SysDictType;
import com.kcht.np.mapper.SysDictDataMapper;
import com.kcht.np.mapper.SysDictTypeMapper;
import com.kcht.np.service.SysDictDataService;
import com.kcht.np.vo.dict.DictDataCanCreateInfo;
import com.kcht.np.vo.dict.DictDataCanModifyInfo;
import com.kcht.np.vo.page.ConditionsQuery;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.List;

@Slf4j
@Service
@DS("kchtnp")
public class SysDictDataServiceImpl extends ServiceImpl<SysDictDataMapper, SysDictData> implements SysDictDataService {

    private final String DICT_TYPE = "dict_type";
    private final String DICT_DATA_SORT = "dict_sort";
    private final String DICT_DATA_STATUS = "status";
    private final String DICT_DATA_LABEL = "dict_label";
    private final String DICT_DATA_VALUE = "dict_value";
    @Autowired
    private SysDictTypeMapper dictTypeMapper;

    @Override
    public SysDictData getById(Serializable id) {
        SysDictData dictData = super.getById(id);
        if(dictData==null){
            throw new ParameterException("无此标识为<"+id+">的字典类型");
        }
        return dictData;
    }
    @Override
    public IPage<SysDictData> page(ConditionsQuery parameter) {
        if (parameter.getConditions().get(DICT_TYPE) == null) {
            throw new ParameterException("未传递" + DICT_TYPE);
        }
        String dictType = parameter.getConditions().get(DICT_TYPE);
        String dictDataLabel=parameter.getConditions().get(DICT_DATA_LABEL);
        String dictDataStatus=parameter.getConditions().get(DICT_DATA_STATUS);
        IPage<SysDictData> page = new Page<>(parameter.getPageNum(), parameter.getPageSize());
        QueryWrapper<SysDictData> queryModel = new QueryWrapper<SysDictData>();
        if(StringUtils.isNotEmpty(dictDataStatus)){
            queryModel=queryModel.eq(DICT_DATA_STATUS,dictDataStatus);
        }
        if(StringUtils.isNotEmpty(dictType)){
            queryModel=queryModel.like(DICT_TYPE,dictType);
        }
        if(StringUtils.isNotEmpty(dictDataLabel)){
            queryModel=queryModel.like(DICT_DATA_LABEL,dictDataLabel);
        }
        return super.page(page,queryModel);
    }

    @Override
    public List<SysDictData> queryDictDataByDictType(String dictType) {
        return super.list(new QueryWrapper<SysDictData>().eq(DICT_TYPE, dictType)
                .eq(DICT_DATA_STATUS, DictStatus.on)
                .orderByAsc(DICT_DATA_SORT));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(DictDataCanCreateInfo newDictData) {
        SysDictData dictData = new SysDictData();
        BeanUtils.copyProperties(newDictData, dictData);
        verifyParam(dictData);
        dictData.setDictSort(addOrder(dictData.getDictSort(), dictData.getDictType()));
        if (dictData.getComment() == null) {
            dictData.setComment("暂无描述");
        }
        super.save(dictData);
    }

    @Override
    public void update(DictDataCanModifyInfo modifyDictData) {
        SysDictData dictData = super.getById(modifyDictData.getId());
        if (dictData == null) {
            throw new ParameterException("无此标识为<" + modifyDictData.getId() + ">的字典数据");
        }
        if(!dictData.getDictLabel().equals(modifyDictData.getDictLabel())){
            int count = super.count(new QueryWrapper<SysDictData>()
                    .eq(DICT_TYPE, dictData.getDictType())
                    .eq(DICT_DATA_LABEL, modifyDictData.getDictLabel()));
            if (count > 0) {
                throw new ParameterException("字典标签已存在");
            }
        }
        if(!dictData.getDictValue().equals(modifyDictData.getDictValue())){
            int count = super.count(new QueryWrapper<SysDictData>()
                    .eq(DICT_TYPE, dictData.getDictType())
                    .eq(DICT_DATA_VALUE, modifyDictData.getDictValue()));
            if (count > 0) {
                throw new ParameterException("字典键值已存在");
            }
        }
        modifyDictData.setDictSort(updateOrder(dictData.getDictSort(),modifyDictData.getDictSort(),dictData.getDictType()));
        BeanUtils.copyProperties(modifyDictData, dictData);
        super.saveOrUpdate(dictData);
    }

    @Override
    public void delete(Long id) {
        SysDictData dictData = super.getById(id);
        if (dictData == null) {
            throw new ParameterException("无此标识为<" + id + ">的字典类型");
        }
        super.removeById(id);
        deleteOrder(dictData.getDictSort(), dictData.getDictType());
    }


    @Transactional(rollbackFor = Exception.class)
    protected int addOrder(int order, String dictType) {
        SysDictData maxModel = super.getOne(new QueryWrapper<SysDictData>().eq(DICT_TYPE, dictType).orderByDesc(DICT_DATA_SORT).last("limit 1"));
        if (maxModel == null) {
            return 1;
        }
        Integer max = maxModel.getDictSort();
        if (order > max || order == 0) {
            return max + 1;
        } else {
            List<SysDictData> list = super.list(new QueryWrapper<SysDictData>().eq(DICT_TYPE, dictType).ge(DICT_DATA_SORT, order));
            for (SysDictData sysDictData : list) {
                sysDictData.setDictSort(sysDictData.getDictSort() + 1);
            }
            super.saveOrUpdateBatch(list);
            return order;
        }
    }

    @Transactional(rollbackFor = Exception.class)
    protected int updateOrder(int oriSort,int nowSort,String dictType) {
        if (nowSort == 0) {
            return oriSort;
        }
        if (oriSort > nowSort) {
            List<SysDictData> list = super.list(new QueryWrapper<SysDictData>()
                    .eq(DICT_TYPE, dictType)
                    .lt(DICT_DATA_SORT, oriSort)
                    .ge(DICT_DATA_SORT, nowSort));
            for (SysDictData sysDictData : list) {
                sysDictData.setDictSort(sysDictData.getDictSort() + 1);
            }
            super.saveOrUpdateBatch(list);
            return nowSort;
        }
        List<SysDictData> list = super.list(new QueryWrapper<SysDictData>()
                .eq(DICT_TYPE, dictType)
                .gt(DICT_DATA_SORT, oriSort)
                .le(DICT_DATA_SORT, nowSort));
        for (SysDictData sysDictData : list) {
            sysDictData.setDictSort(sysDictData.getDictSort() - 1);
        }
        super.saveOrUpdateBatch(list);
        SysDictData maxModel = super.getOne(new QueryWrapper<SysDictData>()
                .eq(DICT_TYPE, dictType)
                .orderByDesc(DICT_DATA_SORT)
                .last("limit 1"));
        Integer max = maxModel.getDictSort();
        if (nowSort > max) {
            nowSort = max + 1;
        }
        return nowSort;
    }

    @Transactional(rollbackFor = Exception.class)
    protected void deleteOrder(int order, String dictType) {
        List<SysDictData> list = super.list(new QueryWrapper<SysDictData>().eq(DICT_TYPE, dictType).gt(DICT_DATA_SORT, order));
        for (SysDictData sysDictData : list) {
            sysDictData.setDictSort(sysDictData.getDictSort() - 1);
        }
        super.saveOrUpdateBatch(list);
    }

    private void verifyParam(SysDictData dictData) {
        SysDictType dictType = dictTypeMapper.selectOne(new QueryWrapper<SysDictType>().eq(DICT_TYPE, dictData.getDictType()));
        if (dictType == null) {
            throw new ParameterException("缺少" + dictData.getDictType() + "的字典类型");
        }
        int count = super.count(new QueryWrapper<SysDictData>()
                .eq(DICT_TYPE, dictData.getDictType())
                .eq(DICT_DATA_LABEL, dictData.getDictLabel())
                .or()
                .eq(DICT_TYPE, dictData.getDictType())
                .eq(DICT_DATA_VALUE, dictData.getDictLabel()));
        if (count > 0) {
            throw new ParameterException("字典标签或字典键值已存在");
        }
    }
}
